﻿// Original author contact info: Owen Emlen (owene_1998@yahoo.com)
// Note: other individuals may also have contributed to this code
// Project hosted on CodePlex.com as of 1/10/2009 at http://wpfimageviewer.codeplex.com
using System;
using System.Collections.Generic;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Threading;
using BrainTechLLC;
using BrainTechLLC.WPF;
using ImageAppViewModels;
using System.Diagnostics;

namespace WpfImageDuplicates
{
    public class FileImageCollectionTimer : BaseNotifyPropertyChanged
    {        
        public Timer _timer;
        private int _timerInterval = 100;
        public ImageCollectionView _collectionView;
        public FileImageCollectionScrollHandler _scrollHandler;
        private int _counter;
        private bool _inTimer;
        private bool _childrenViewsProcessed = true;
        private List<FileImageViewModel> _childrenViews;
        private object _lockObj = new object();
        private object _timerLockObj = new object();
        private int _doneStuffCounter;

        public FileImageCollectionTimer(ImageCollectionView collectionView, FileImageCollectionScrollHandler scrollHandler)
        {
            _collectionView = collectionView;
            _scrollHandler = scrollHandler;

            if (_timer == null)
            {
                _timer = new Timer(timer_Tick, null, 500, _timerInterval);
            }
        }

        //public void CleanThumbnailViews()
        //{
        //    _collectionView.CleanThumbnailViews();
        //}

        public List<ThumbnailView> GetAllThumbnailViews()
        {
            return _collectionView.GetAllThumbnailViews();
        }

        public List<FileImageViewModel> GetAllVisibleThumbnailViews()
        {
            //CleanThumbnailViews();
            //return _scrollHandler.GetAllVisibleThumbnailViews(GetAllThumbnailViews());
            List<FileImageViewModel> results = new List<FileImageViewModel>();
            if (_collectionView != null && _collectionView._wrapPanel != null)
            {
                for (int n = _collectionView._wrapPanel.firstVisibleItemIndex; n <= _collectionView._wrapPanel.lastVisibleItemIndex; n++)
                {
                    results.Add(_collectionView.Displayed[n]);
                }
            }
            return results;
        }

        private void timer_Tick(object state)
        {
            bool doneSomething = false;

            if (_inTimer || !_childrenViewsProcessed)
            {
                return;
            }

            ScrollViewer sv = _scrollHandler.ScrollViewer;

            if (sv == null)
                return;

            _inTimer = true;

            try
            {
                lock (_timerLockObj)
                {
                    DataLoader._metaData.SaveIfDirty(FilePaths._metaDataFilePath);

                    if (_childrenViews != null)
                    {
                        try
                        {
                            if (_childrenViews.Count > 0)
                            {
                                _collectionView._vm._lastVisibleCount = _childrenViews.Count;

                                List<FileImageViewModel> children = new List<FileImageViewModel>();

                                for (int n = 0; n < _childrenViews.Count; n++)
                                {
                                    children.Add(_childrenViews[n]);
                                }

                                _collectionView.ForceRefresh = false;

                                if (children.Count > 0)
                                {
                                    HandleThumbPreloading(children);
                                    doneSomething = true;
                                }

                                _childrenViews.Clear();
                            }

                            _childrenViews = null;
                            _collectionView.MarkThumbnailNeedsClean();
                        }
                        catch (Exception ex2)
                        {
                            Console.WriteLine(ex2.ToString());
                        }
                    }

                    if (_collectionView._resized || _scrollHandler.UpdateVerticalOffset() || _collectionView.ForceRefresh)
                    {
                        if (_collectionView._resized)
                        {
                            _collectionView._resized = false;
                            _scrollHandler._needsRecalcVisible = true;
                            _scrollHandler.RecalcScrollViewerInfo();
                        }

                        if (_collectionView.ForceRefresh)
                        {
                            _collectionView.ForceRefresh = false;

                            // Not sure all these are necessary...
                            _collectionView._resized = false;
                            _scrollHandler._needsRecalcVisible = true;
                            _scrollHandler.RecalcScrollViewerInfo();
                        }

                        if (_childrenViews == null)
                        {
                            _childrenViewsProcessed = false;
                            Window1.MainWindow.Dispatcher.RunOnDispatcher(new VoidDelegate(() =>
                            {
                                try
                                {
                                    if (_childrenViews == null)
                                    {
                                        lock (_lockObj)
                                        {
                                            Interlocked.CompareExchange<List<FileImageViewModel>>(ref _childrenViews, GetAllVisibleThumbnailViews(), null);
                                        }
                                        _childrenViewsProcessed = true;
                                    }
                                }
                                catch (Exception ex)
                                {
                                    Console.WriteLine(ex.ToString());
                                }
                            }),
                            DispatcherPriority.Send); // was DispatcherPriority.Send

                            doneSomething = true;
                        }
                    }

                    if (doneSomething)
                    {
                        _doneStuffCounter++;

                        if (_doneStuffCounter > 10 && _timerInterval != Math.Min(_timerInterval + 50, 71))
                        {
                            _timerInterval = Math.Min(_timerInterval + 50, 71);
                            _timer.Dispose();
                            _timer = null;
                            _timer = new Timer(timer_Tick, null, 50, _timerInterval);
                        }
                    }
                    else
                    {
                        _doneStuffCounter = 0;

                        if (_timerInterval > 70 && _timerInterval != Math.Max(_timerInterval - 50, 70))
                        {
                            _timerInterval = Math.Max(_timerInterval - 50, 70);
                            _timer.Dispose();
                            _timer = null;
                            _timer = new Timer(timer_Tick, null, 50, _timerInterval);
                        }
                    }

                    if (_collectionView.ThumbsHandler != null && _collectionView.ThumbsHandler.ThumbCleanup != null)
                    {
                        _collectionView.ThumbsHandler.ThumbCleanup.HandleCleanCycle();
                    }

                    HandleCheckCleanupImageCollectionViewModel();
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
            finally
            {
                _inTimer = false;
            }
        }

        private void HandleThumbPreloading(List<FileImageViewModel> children)
        {
            if (children.Count > 0)
            {
                Thread.Sleep(20);
                if (_collectionView != null && _collectionView.ThumbsHandler != null && _collectionView.ThumbsHandler.ThumbPreloader != null)
                {
                    _collectionView.ThumbsHandler.ThumbPreloader.Clear();
                }
            }

            foreach (var item in children)
            {
                if (item.Dirty && item.ThumbVisibleOnScreen)
                {
                    if (_collectionView.ThumbsHandler.ThumbPreloader.EnqueueIfNotInList(item))
                    {
                        Debug.WriteLine(string.Format("Enqueing {0} at {1}", item._fileName, DateTime.Now.Millisecond.ToString()));
                    }
                }
                else
                {
                    Debug.WriteLine(string.Format("Thumb {0} visible={1}, dirty={2}", item.FileNameOnly, item.ThumbVisible, item.Dirty));
                }
            }
        }

        private void HandleCheckCleanupImageCollectionViewModel()
        {
            if (_counter++ % 40 == 39)
            {
                try
                {
                    if (_collectionView != null && _collectionView.ThumbsHandler != null)
                    {
                        _collectionView.ThumbsHandler.ThumbCleanup.HandleCleanupCollection();
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.ToString());
                }
            }
        }

    }
}
